--[[

    Client Identifier library.
    Version 27/01/2019.

    Description:
    A Lua library to identify client(s) from UI module.


        MIT License

        Copyright (c) 2018 Anggara Yama Putra

        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.

]]


-- Remove unecessary table(s).
ClientID.Game = nil;


-- Local variables.
local module = ClientID.UI;
local debug = ClientID.Debug;
local syncvalue = ClientID.SyncValue;
local enum = ClientID.Enum;
local isVerified = false;
local doVerify = false;
local playerID = nil;
local nextVerifyTime = nil;


-- SyncValue init(s).
syncvalue.Verify.Instance = UI.SyncValue.Create( syncvalue.Verify.NAME );
syncvalue.CurrentTime.Instance = UI.SyncValue.Create( syncvalue.CurrentTime.NAME );


-- Returns current game time.
function module:GetGameTime()
    return syncvalue.CurrentTime.Instance.value;
end


-- Returns my unique identity.
function module:GetID()
    return playerID;
end


-- Checks whether my unique ID is verified.
function module:IsVerified()
    return isVerified;
end


-- Checks whether the ID verification has started.
function module:IsVerificationStarted()
    return doVerify;
end


-- Verifies my player ID.
function module:StartVerification()
    -- Stop the old verification first.
    if self:IsVerificationStarted()
    then
        debug:print( "[UI] Halting current verification." );
        self:StopVerification();
    end

    UI.Signal( enum.SIGNAL.NOT_VERIFIED );
    isVerified = false;
    doVerify = true;
    nextVerifyTime = self:GetGameTime() + self.VERIFY_DELAY;
    UI.Signal( enum.SIGNAL.VERIFY );
    debug:print( "[UI] ID verification is started." );
end


-- Stop the ID verification.
function module:StopVerification()
    if self:IsVerificationStarted() == false then return end
    doVerify = false;
    debug:print( "[UI] ID verification is halted." );
end


-- Assigns my player ID.
function module:Assign( time )
    if self:IsVerified() then return end
    if self:IsVerificationStarted() then return end
    if time == nil then return end

    local screenSize = UI.ScreenSize();
    local int_time = math.ceil( time + math.random(screenSize.height,screenSize.width) );
    debug:print( string.format( "[UI] int_time (%i)." , int_time ) );

    -- This is my ID.
    playerID = int_time;

    -- Sends "OK" signal.
    local signal = enum.SIGNAL.OK + self:GetID();
    UI.Signal( signal );

    debug:print( string.format( "[UI] playerID(%i)." , self:GetID() ) );

    -- Verify this ID.
    self:StartVerification();
end


-- SyncValue.Verify OnSync hook.
function syncvalue.Verify:OnSync()
    local currentTime = module:GetGameTime();
    if nextVerifyTime ~= nil and currentTime ~= nil and nextVerifyTime <= currentTime
    then
        local value = syncvalue.Verify.Instance.value;
        if doVerify and value ~= nil 
        then
            isVerified = ( value == module:GetID() );

            if module:IsVerified()
            then
                debug:print( "[UI] My ID is Verified." );
                UI.Signal( enum.SIGNAL.VERIFIED );
                module:OnVerify( true );
            else
                debug:print( "[UI] My ID is NOT Verified." );
                UI.Signal( enum.SIGNAL.NOT_VERIFIED );
                module:OnVerify( false );
            end
        end
        module:StopVerification();
    end
end


-- Hookable event: OnVerify().
function module:OnVerify( isVerified )
end


-- SyncValue.CurrentTime OnSync hook.
function syncvalue.CurrentTime:OnSync()
    local value = module:GetGameTime();

    if value ~= nil
    then
        module:Assign( value );
    end
end


-- Default hook executions.
function syncvalue.CurrentTime.Instance:OnSync()
    ClientID.SyncValue.CurrentTime:OnSync();
end
function syncvalue.Verify.Instance:OnSync()
    ClientID.SyncValue.Verify:OnSync()
end


print( "UI.ClientIdentifier.Main is loaded!" );

